#include "AudioSystem.h"

using namespace std;

/*---------------------------------------------------------------------------------------
--	FUNCTION:	AudioSystem::AudioSystem()
--
--	DATE:			April 07, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		John Kuo
--
--	PROGRAMMER:		Brad Paugh
--
--      INTERFACE:      AudioSystem::AudioSystem()
--
--	RETURNS:
--
--	NOTES:
--		default constructor for the AudioSystem
---------------------------------------------------------------------------------------*/
AudioSystem::AudioSystem()
{
	currentBuffer = 0;
    currentVolume = 0xFFFF;  // 50% of the volume level
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	AudioSystem::playBuffer(char* audioBuffer, int length)
--
--	DATE:			April 07, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		John Kuo
--
--	PROGRAMMER:		Brad Paugh
--
--  INTERFACE:      void AudioSystem::playBuffer(char* audioBuffer, int length)
--						char* audioBuffer - the audio data to play
--						int length length of buffer
--
--	RETURNS: void
--
--	NOTES:
--		function to output the contents from the buffer to the output device
---------------------------------------------------------------------------------------*/
void AudioSystem::playBuffer(char* audioBuffer, int length)
{
    if (currentBuffer == NUM_OF_BUFFERS)
	{
		currentBuffer = 0;
	}

	bufferData[currentBuffer] = (char*)malloc(length);
	memcpy(bufferData[currentBuffer], audioBuffer, length);

	headers[currentBuffer].lpData = bufferData[currentBuffer];
	headers[currentBuffer].dwBufferLength = length;
	headers[currentBuffer].dwBytesRecorded =  0;
	headers[currentBuffer].dwUser = 0;
	headers[currentBuffer].dwFlags = 0;
	headers[currentBuffer].dwLoops = 0;

	MMRESULT mr;
	if ((mr = waveOutPrepareHeader(audioDevice,&headers[currentBuffer],sizeof(headers[currentBuffer]))) != MMSYSERR_NOERROR)
	{
		char* txt = (char*)malloc(1024);
		waveOutGetErrorText(mr, (WCHAR*)txt, 1024);
		cout << txt;
	}
	if ((mr = waveOutWrite(audioDevice,&headers[currentBuffer],sizeof(headers[currentBuffer]))) != MMSYSERR_NOERROR)
	{
		char* txt = (char*)malloc(1024);
		waveOutGetErrorText(mr, (WCHAR*)txt, 1024);
		cout << txt;
	}
    currentBuffer++;
}
/*---------------------------------------------------------------------------------------
--	FUNCTION:	AudioSystem::stop()
--
--	DATE:			April 07, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		John Kuo
--
--	PROGRAMMER:		Brad Paugh
--
--  INTERFACE:      AudioSystem::stop()
--
--	RETURNS:
--
--	NOTES:
--		stops the audio from playing
---------------------------------------------------------------------------------------*/
void AudioSystem::stop()
{
	currentBuffer = 0;
	waveOutReset(audioDevice);
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	AudioSystem::changeVolume(DWORD volumeLevel)
--
--	DATE:			April 07, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		John Kuo
--
--	PROGRAMMER:		Brad Paugh
--
--  INTERFACE:      AudioSystem::changeVolume(DWORD volumeLevel)
--						DWORD volumeLevel - level of the volume
--
--	RETURNS:
--
--	NOTES:
--		function to change the volume
---------------------------------------------------------------------------------------*/
void AudioSystem::changeVolume(DWORD volumeLevel)
{
    waveOutSetVolume(audioDevice, MAKELONG(LOWORD(volumeLevel), LOWORD(volumeLevel)));
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	AudioSystem::extractHeaderInfo(FILE* fp)
--
--	DATE:			April 07, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		John Kuo
--
--	PROGRAMMER:		Brad Paugh
--
--  INTERFACE:      AudioSystem::extractHeaderInfo(FILE* fp)
--						FILE* fp - the file to extract header from
--
--	RETURNS: char* - the header in packet sending form
--
--	NOTES:
--		function to retrieve the HeaderInfo of the music file
---------------------------------------------------------------------------------------*/
char* AudioSystem::extractHeaderInfo(FILE* fp)
{
	if (fp) 
	{ 
		BYTE id[4];
		DWORD size;
		short format_tag, channels, block_align, bits_per_sample; 
		DWORD format_length, sample_rate, avg_bytes_sec;
		BYTE junk[8];

		fread(id, sizeof(BYTE), 4, fp);
		if (!memcmp(id, "RIFF", 4)) 
		{
			fread(&size, sizeof(DWORD), 1, fp);
			fread(&id, sizeof(BYTE), 4, fp);
			if (!memcmp(id,"WAVE", 4)) 
			{
				fread(&id, sizeof(BYTE), 4, fp);
				fread(&format_length, sizeof(DWORD),1,fp); 
				fread(&format_tag, sizeof(short), 1, fp); 
				fread(&channels, sizeof(short),1,fp); 
				fread(&sample_rate, sizeof(DWORD), 1, fp); 
				fread(&avg_bytes_sec, sizeof(DWORD), 1, fp); 
				fread(&block_align, sizeof(short), 1, fp); 
				fread(&bits_per_sample, sizeof(short), 1, fp);
				fread(&junk, 8, 1, fp);
			} 
			else 
                                ;
		} 
		else 
                        ;
		format.wFormatTag = format_tag;
		format.nChannels  = channels;
		format.nSamplesPerSec = sample_rate;
		format.wBitsPerSample = bits_per_sample;
		format.nBlockAlign = block_align;
		format.nAvgBytesPerSec = avg_bytes_sec;
		format.cbSize = 0;
		MMRESULT mr;
		if ((mr = waveOutOpen(&audioDevice, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL)) != MMSYSERR_NOERROR)
		{
			char* txt = (char*)malloc(1024);
			waveOutGetErrorText(mr, (WCHAR*)txt, 1024);
                        ;
			exit(1);
		}
		int bytesWritten;
        bytesWritten = sprintf(headerData, "%d|%d|%lu|%d|%d|%lu|", format_tag, channels, sample_rate, bits_per_sample, block_align, avg_bytes_sec);
		for (int i = bytesWritten; i < 23; i++)
		{
			headerData[i] = '|';
		}
		return headerData;
	}
	return 0;
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	AudioSystem::extractHeaderFromPacket(char* packet)
--
--	DATE:			April 07, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		John Kuo
--
--	PROGRAMMER:		Brad Paugh
--
--  INTERFACE:      AudioSystem::extractHeaderFromPacket(char* packet)
--						char* packet - the packet to extract header from
--
--	RETURNS:		char* - the position of the data(non header info)
--
--	NOTES:
--		function to retrieve the header info sent out by the server packet
---------------------------------------------------------------------------------------*/
char* AudioSystem::extractHeaderFromPacket(char* packet)
{
    char*           token;

    unsigned int    samplesPerSecToken,
                    avgBytesPerSecToken;

    int             count = 0;

    bool            changed = false;

    char* header = (char*)malloc(24);
	memcpy(header, packet, 23);
    header[23] = '\0';

    while ((token = strtok(header, "|")) != 0)
	{
		header = 0;
		if (count == 0)
		{
			if (format.wFormatTag != atoi(token))
			{
				format.wFormatTag = atoi(token);
				changed = true;
			}
		}
		if (count == 1)
		{
			if (format.nChannels != atoi(token))
			{
				format.nChannels = atoi(token);
				changed = true;
			}
		}
		if (count == 2)
		{
            samplesPerSecToken = atoi(token);

            if (format.nSamplesPerSec != samplesPerSecToken)
			{
                format.nSamplesPerSec = samplesPerSecToken;
				changed = true;
			}
		}
		if (count == 3)
		{
			if (format.wBitsPerSample != atoi(token))
			{
				format.wBitsPerSample = atoi(token);
				changed = true;
			}
		}

		if (count == 4)
		{
			if (format.nBlockAlign != atoi(token))
			{
				format.nBlockAlign = atoi(token);
				changed = true;
			}
		}
		if (count == 5)
		{
            avgBytesPerSecToken = atoi(token);

            if (format.nAvgBytesPerSec != avgBytesPerSecToken)
			{
                format.nAvgBytesPerSec = avgBytesPerSecToken;
				changed = true;
			}
                        break;
		}
		format.cbSize = 0;
		count++;
	}
	if (changed)
	{
		waveOutClose(audioDevice);
		MMRESULT mr;
		if ((mr = waveOutOpen(&audioDevice, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL)) != MMSYSERR_NOERROR)
		{
			char* txt = (char*)malloc(1024);
			waveOutGetErrorText(mr, (WCHAR*)txt, 1024);
                        ;
			exit(1);
		}
	}

	return &packet[23];
}

/*---------------------------------------------------------------------------------------
--	FUNCTION:	AudioSystem::getMsPerPacket(int packetSize)
--
--	DATE:			April 07, 2010
--
--	REVISIONS		(Date and Description):
--
--	DESIGNER:		John Kuo
--
--	PROGRAMMER:		Brad Paugh
--
--  INTERFACE:      AudioSystem::getMsPerPacket(int packetSize)
--						int packetSize - size of the packet
--
--	RETURNS: int
--
--	NOTES:
--		function to calculate the the speed of the packet in milliseconds
---------------------------------------------------------------------------------------*/
int AudioSystem::getMsPerPacket(int packetSize)
{
	int millisecs;
	millisecs = packetSize/(format.nAvgBytesPerSec/1000); //convert to avg bytes per millisec
	return millisecs;
}
